
public class DataTable
{
  int numOfRows, numOfColumns;
  String[][] data;
  String[] columnNames;
  
  String[] maxStringEltInColumn;
  float[] maxFloatEltInColumn;
  int[] maxIntEltInColumn;
  
  DataTable( String filename )
  {
    //LOAD DATA
    String[] rows = loadStrings( filename );
    String[] columns = split( rows[0], "\t" ); //split by tabs
    
    columnNames = subset(columns, 0);//gets all column names from 0th column to last column
    numOfColumns = columnNames.length; //num of columns is equal to columnNames.length
    
    data = new String[ rows.length-1 ][ ];//start out n arrays, where n equals number of rows
    
    println( "I see " + rows.length + " lines in your file");
    println( "With " + numOfColumns + " columns separated by tab delimiters" ); 
    
    // split rows into columns
    // start reading at row 1, because the first row was only the column headers
    for (int i = 1; i < rows.length; i++) {
      if (trim(rows[i]).length() == 0) {
        continue; // skip empty rows
      }
      if (rows[i].startsWith("#")) {
        continue;  // skip comment lines
      }
      
      // split the row on the delimiter
      String[] pieces = split(rows[i], '\t');
      
      // copy data into the table starting at pieces[0]
      data[numOfRows] = subset(pieces, 0);

      // increment the number of valid rows found so far
      numOfRows++;      
    }
    // resize the 'data' array as necessary
    data = (String[][]) subset(data, 0, numOfRows);
    
    //COMPUTE MAXIMUMS
    maxStringEltInColumn = new String[ numOfColumns ];
    maxIntEltInColumn = new int[ numOfColumns ];
    maxFloatEltInColumn = new float[ numOfColumns ]; 
    for(int col = 0; col < numOfColumns; col++)
    {
        maxStringEltInColumn[ col ] = data[ 0 ][ col ];
        maxIntEltInColumn[ col ] = parseInt( data[ 0 ][ col ] );
        maxFloatEltInColumn[ col ] = parseFloat( data[ 0 ][ col ] );
        
        for(int row = 0; row < numOfRows; row++)
        {
          if( maxStringEltInColumn[ col ].compareTo( data[row][col] ) < 0 )
            maxStringEltInColumn[col] = data[row][col];
          if( maxIntEltInColumn[ col ] < parseInt( data[row][col] ) )
            maxIntEltInColumn[col] = parseInt( data[row][col] );
          if( maxFloatEltInColumn[ col ] < parseFloat( data[row][col] ) )
            maxFloatEltInColumn[col] = parseFloat( data[row][col] );  
        }
    }
  }
  
  //---------------------------------------------------GETTERS--------------------------------------------------
  
  //---------------------BASIC GETTERS----------------
  /*
  Method: getStringElement
  Parameters:  row and column
  Returns:  String elt at that position
  */
  String getStringElement( int row, int col )
  {
    return data[ row ][ col ];
  }
  
   /*
  Method: getIntElement
  Parameters:  row and column
  Returns:  Int elt at that position
  User beware:  if elt is not an int, will return NAN
  */
  int getIntElement( int row, int col )
  {
    return parseInt( data[ row ][ col ] ); 
  }
  
   /*
  Method: getFloatElement
  Parameters:  row and column
  Returns:  Float elt at that position.  
  User beware:  if elt is not a float, will return NAN
  */
  float getFloatElement( int row, int col )
  {
    return parseFloat( data[ row ][ col ] );
  }
  //-------------------END BASIC GETTERS--------------
  //---------------------GET MAXIMUM------------------
  /*
  Method: getStringElement
  Parameters:  row and column
  Returns:  String elt at that position
  */
  String getMaxStringInColumn( int col )
  {
    return maxStringEltInColumn[ col ];
  }
  
   /*
  Method: getIntElement
  Parameters:  row and column
  Returns:  Int elt at that position
  User beware:  if elt is not an int, will return NAN
  */
  int getMaxIntInColumn( int col )
  {
    return maxIntEltInColumn[ col ] ; 
  }
  
   /*
  Method: getFloatElement
  Parameters:  row and column
  Returns:  Float elt at that position.  
  User beware:  if elt is not a float, will return NAN
  */
  float getMaxFloatInColumn( int col )
  {
    return maxFloatEltInColumn[ col ] ;
  }
  //-------------------END GET MAXIMUM----------------
  //---------------------GET FIRST OF-----------------
   /*
  Method: getFirstRowOfIntElt
  Parameters:  int column, int elt
  Returns:  row at which integer element first appears
  User beware:  if elt is not an int, will return -1, because won't be found
  */
  int getFirstRowOfIntElt( int col, int elt )
  {
    for(int row = 0; row < data.length; row++)
    {
      if( parseInt(data[row][col]) == elt )
        return row;
    }
    return -1; //not found
  }
  
  /*
  Method: getFirstRowOfFloatElt
  Parameters:  int column, float elt
  Returns:  row at which float element first appears
  User beware:  if elt is not a float, will return -1, because won't be found
  */
  int getFirstRowOfFloatElt( int col, float elt )
  {
    for(int row = 0; row < data.length; row++)
    {
      if( parseFloat(data[row][col]) == elt )
        return row;
    }
    return -1; //not found
  }
  
  /*
  Method: getFirstRowOfStringElt
  Parameters:  int column, String elt
  Returns:  row at which String element first appears
  User beware:  if elt is not a String, will return -1, because won't be found
  */
  int getFirstRowOfStringElt( int col, String elt )
  {
    for(int row = 0; row < data.length; row++)
    {
      if( data[row][col].compareTo( elt ) == 0 )
        return row;
    }
    return -1; //not found
  }
  //-------------------END GET FIRST OF---------------
  
  //---------------------GET LAST OF-----------------
   /*
  Method: getLastRowOfIntElt
  Parameters:  int column, int elt
  Returns:  row at which integer element last appears
  User beware:  if elt is not an int, will return -1, because won't be found
  */
  int getLastRowOfIntElt( int col, int elt )
  {
    int rowToReturn = -1;
    for(int row = 0; row < data.length; row++)
    {
      if( parseInt(data[row][col]) == elt )
        rowToReturn = row;
    }
    return rowToReturn; //not found
  }
  
  /*
  Method: getLastRowOfFloatElt
  Parameters:  int column, float elt
  Returns:  row at which float element last appears
  User beware:  if elt is not a float, will return -1, because won't be found
  */
  int getLastRowOfFloatElt( int col, float elt )
  {
    int rowToReturn = -1;
    for(int row = 0; row < data.length; row++)
    {
      if( parseFloat(data[row][col]) == elt )
        rowToReturn = row;
    }
    return rowToReturn; //not found
  }
  
  /*
  Method: getLastRowOfStringElt
  Parameters:  int column, String elt
  Returns:  row at which String element last appears
  User beware:  if elt is not a String, will return -1, because won't be found
  */
  int getLastRowOfStringElt( int col, String elt )
  {
    int rowToReturn = -1;
    for(int row = 0; row < data.length; row++)
    {
      if( data[row][col].compareTo( elt ) == 0 )
        rowToReturn = row;
    }
    return rowToReturn; //not found
  }
  //-------------------END GET LAST OF---------------
  //------------------------------------------------END GETTERS--------------------------------------------------
  
  //------------------------------------------------UTILITY METHODS----------------------------------------------
    
  /*
  outputs data to stdout
  */
  String toString()
  {
    String toReturn = "";
    for(int i =0; i < data.length; i++)
    {
      toReturn += i + "\t";
      for(int j = 0; j < data[i].length; j++)
      {
        toReturn += data[i][j] + "\t";
      }
      toReturn += "\n";
    }
    return toReturn;
  }
  
  //------------------------------------------------END UTILITY METHODS------------------------------------------
  
}

